/*********************************************************************************
 *      Copyright:  (C) 2022 South-Central Minzu University
 *                  All rights reserved.
 *
 *       Filename:  client.c
 *    Description:  This file：Raspberry pie regularly obtains the temperature and reports it to the server 
 *                 
 *        Version:  1.0.0(12/04/22)
 *         Author:  zhangkang <2980640573@qq.com>
 *      ChangeLog:  1, Release initial version on "12/04/22 15:59:59"
 *                 
 ********************************************************************************/

#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>          
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <getopt.h>
#include <time.h>
#include <sqlite3.h>
#include <signal.h>
#include <libgen.h>
#include <linux/tcp.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netdb.h>

#include "sqlite3.h"
#include "logger.h"



void useage(char *progname);
void sig_handle(int signum);
int get_sn(char* SN,int SN_LEN);

int g_sigstop=0;





 int main(int argc,char * argv[])
{
    struct sigaction        sigign;
    struct timeval          tv;
    struct tm*              st;
    struct sockaddr_in 	    servaddr;
    char                    db_name[16]="temp_cli.db";
    char                   *servip=NULL;
    char                   *buf_data[64];
    char                    SN[16];
    char                    datatime[128];
    char                    buff_temp[16];
    char                    buff_id[8];
    char                    buf_write[128];
    char                    buf_send[128];
    long	                current_time = 0;
    long	                pick_time = 0;
    float                   temp;
    int                     opt;
    int                     idx;
    int		                daemon_run =0;
    int                     ret_write=-1;
    int                     conflag=1;
    int                     second=0;  
    int		                port =0;
    int                     sockfd=-1;
    int                     sample=0;
    struct option           opts[] = {
                                         {"ipaddr",required_argument,NULL,'i'},
                                         {"h_alias",required_argument,NULL,'a'},
                                         {"port",required_argument,NULL,'p'},
                                         {"second",required_argument,NULL,'t'},
                                         {"daemon", no_argument, NULL, 'b'},
                                         {"help",no_argument,NULL,'h'},
                                         {NULL,0,NULL,0}
                                     };
   
    
    
    while((opt = getopt_long(argc,argv,"i:p:t:bh",opts,&idx)) != -1)
    {
        switch(opt)
        {
            case 'i':
                     servip = optarg;
                     break;
            case 'p':
                     port = atoi(optarg);
                     break;
            case 't':
                     second= atoi(optarg);
                     break;
            case 'b':
                     daemon_run = 1;
                     break;
            case 'h':
                     useage(argv[0]);
                     return 0;
        }
     }
       
    
               /*command line error*/
    if(!((servip&&port&&second)))
    {
         useage(argv[0]);
         return 0;
    }

                         /*zlog*/
    if( logger_init("stdout", LOG_LEVEL_DEBUG) < 0)
    {
        fprintf(stderr, "initial logger system failure\n");
        return 1;
    }    
  
        /*daemon*/
    if(daemon_run)
	  {
		    if(daemon(1, 0))
		    {
                log_error("Running daemon failure:%s\n", strerror(errno));
		    }
        else
        {
            if( logger_init("running.log", LOG_LEVEL_DEBUG) < 0)
            { 
                fprintf(stderr, "initial logger system failure\n");
                return 2;
            }
      		  log_info("Running daemon successfully\n");
        }
	  }
   
         /*signal*/
    signal(SIGINT,sig_handle);
    signal(SIGTERM,sig_handle);

    
          /*socket init*/
    if( ( client_socket_init (servip,port,&sockfd) ) <0 )
    {
        log_warn("socket first initialization failed\n");
    }
    else
    {
        log_info("socket first initialization scuessfully\n");
    }
   
         /*sqlite init*/
   if( ( sqlite_init(db_name) ) < 0  )
   {
       log_warn("sqlite initialization failed\n");
   }
   else
   {
       log_info("sqlite initialization scuessfully\n");
   }
   
    
        
    while(!g_sigstop)
    {                                    
                        /* when time is ready,start sampleand take sample=1 */
        gettimeofday(&tv, NULL);
        current_time=tv.tv_sec;
        if( (current_time-pick_time) >= second  )
        {
            sample=1;       
                    
                    /*packed data*/
            pick_time=get_time(datatime,sizeof(datatime));
            get_sn( SN,sizeof(SN) );
            get_temperature( &temp );
            memset(buff_temp,0,sizeof(buff_temp));
            snprintf(buff_temp,sizeof(buff_temp),"%.3f",temp);
        }
        
        
                       /* when time is noy ready,start sampleand take sample=0 */
        else
        {
            sample=0;
            log_info("This is no time to sample!\n");
        }
       
       
                          /*if socket disconnected :take conflag=0,program will go to zero;
		                        if socket connected    :take conflag=1, program will go to one; */
       
        
        if( 0 == socket_connect_check( sockfd) )
		{
            conflag=0;
            close(sockfd);
            sockfd=-1;
            
            if( ( client_socket_init (servip,port,&sockfd) ) <0 )
            {
                log_warn("socket restart initialization failed\n");
                log_info(" go to 0\n");               
            }
            else
            {
                conflag=1;
                log_info("socket restart initialization scuessfully\n");
            }    
        }
        
        else
        {
            conflag=1;
            log_info(" go to 1\n");
        }
        
                  
                  
                   /*if socket connected*/
        if(conflag)
        {
                   /*if sample,client will send this data to server*/  
            if( 1==sample )
            {
                memset(buf_write,0,sizeof(buf_write));
                snprintf(buf_write,sizeof(buf_write),"%s/%s/%s",SN,datatime,buff_temp);
                log_debug("buf_write:%s\n",buf_write);
                ret_write = write(sockfd,buf_write,sizeof(buf_write));
               
                /*if the sending fails, the data will be saved to the database*/
                if(ret_write<0)
                {
                    sqlite_insert_data(SN,datatime,buff_temp);
                    log_error("send data to server failure:%s",strerror(errno));
                    close(sockfd);
                    sockfd=-1;
                }   
                else
                {                 
                    log_info("sample data strat to send\n");
                }
            }
            
                  /*if no sample,check whether there id data in the database*/
            else
            {
                if(  ( sqlite_get_count() ) > 0  )
                {
                    sqlite_get_data( buf_send,sizeof(buf_send), sqlite_get_count() );
                    ret_write = write(sockfd,buf_send,sizeof(buf_send));
                    if(ret_write<0)
                    {
                        log_error("send data to server failure:%s",strerror(errno));
                        close(sockfd);
                        sockfd=-1;
                    }      
                    else
                    {
                       sqlite_deldata( sqlite_get_count() );
                       log_info("sqlite data strat to send and delete\n");
                    }
                }                
                else
                {
                    log_info("sqlite has no data\n");
                }
            }
        }
         
                    /*if socket disconnected*/
        if(!conflag)
        {
            /*if sample=1,the data will be saved to the database*/
            if( 1==sample )
            {
                log_info("SN:%s,datatime:%s,buff_temp:%s\n",SN,datatime,buff_temp);
                sqlite_insert_data(SN,datatime,buff_temp);
            }
            
            /*if sample=0,nothing to do*/
            else
            {
                log_info("nothing to do \n");
            }
        } 
        sleep(2);
    }                                                                                                            
    sqlite_close_db();
    log_warn("I QUIT GRACEFULLY\n"); 
    logger_term();
}
     

void useage(char *progname)//命令行参数；
{
    log_warn("%s useage:\n",progname);
    log_warn("-i(--ipaddr):specify server IP address\n");
    log_warn("-p(--port):specify server  port\n");
    log_warn("-t(--second):specify second\n");
    log_warn("-b[daemon]:Start daemon!\n");
    log_warn("-h(--help):print this help information\n");
    return;
}

void sig_handle(int signum)               //安装信号
{
    log_warn("catch signal [%d]\n",signum);
    g_sigstop = 1;
}
 
int get_sn(char* SN,int SN_LEN)          //获取SN
{
    int sn=1;
    memset(SN,0,sizeof(SN));
    snprintf(SN,16,"zk%04d",sn);
    return 0;  
} 

